package Vshift

import VShiftInstr._
import chisel3._
import chisel3.util._


class WbData extends Bundle{
  val result_low = UInt(WIDTH64.W)
  val result_hig = UInt(WIDTH64.W)
}


class VShiftWb(sec: Int = 1) extends Module {
  val io = IO(new Bundle {

    val vcon = Input(new Vcon())
    val velem = Input(new Velem())
    val vdec = Input(new Vdec())
    val dstData = Input(new DstData())

    val wbData = Output(new WbData())
  })

  //---------------------------------------------------------------------=
  //sec and Q

  val secValid = if (sec==1) 1.U else 2.U
  val CEValid = Wire(UInt(1.W))
  when(secValid === 1.U){
    when(io.vcon.long === 1.U){
      when(io.vdec.Q === 1.U){
        CEValid := 0.U
      }.otherwise{
        CEValid := 1.U
      }
    }.otherwise{
      CEValid := 1.U
    }
  }.elsewhen(secValid === 2.U){
    when(io.vcon.narrow === 1.U){
      CEValid := 1.U
    }.otherwise{
      when(io.vdec.Q === 1.U){
        CEValid := 1.U
      }.otherwise{
        CEValid := 0.U
      }
    }
  }.otherwise{
    CEValid := 0.U
  }

  //wb_low_data
  io.wbData.result_low := 0.U

  when(CEValid === 1.U & (secValid === 1.U)){
    when(io.vcon.long === 1.U){
      when(io.velem.elementNum === 1.U && io.velem.esize === 64.U){
        io.wbData.result_low := io.dstData.LongResult1_128(0)(63,0)
      }.elsewhen(io.velem.elementNum === 2.U && io.velem.esize === 32.U){
        io.wbData.result_low := io.dstData.LongResult2_64(0)
      }.elsewhen(io.velem.elementNum === 4.U && io.velem.esize === 16.U){
        io.wbData.result_low := Cat(io.dstData.LongResult4_32(1), io.dstData.LongResult4_32(0))
      }.elsewhen(io.velem.elementNum === 8.U && io.velem.esize === 8.U){
        io.wbData.result_low := Cat(io.dstData.LongResult8_16(3), io.dstData.LongResult8_16(2), io.dstData.LongResult8_16(1), io.dstData.LongResult8_16(0))
      }
    }.elsewhen(io.vcon.narrow === 1.U){
      when(io.vdec.Q === 0.U) {
        when(io.velem.elementNum === 1.U && io.velem.esize === 64.U) {
          io.wbData.result_low := io.dstData.result1_64(0)
        }.elsewhen(io.velem.elementNum === 2.U && io.velem.esize === 32.U) {
          io.wbData.result_low := Cat(io.dstData.result2_32(1),io.dstData.result2_32(0))
        }.elsewhen(io.velem.elementNum === 4.U && io.velem.esize === 16.U) {
          io.wbData.result_low := Cat(io.dstData.result4_16(3),io.dstData.result4_16(2),io.dstData.result4_16(1),io.dstData.result4_16(0))
        }.elsewhen(io.velem.elementNum === 8.U && io.velem.esize === 8.U) {
          io.wbData.result_low := Cat(io.dstData.result8_8(7),io.dstData.result8_8(6),io.dstData.result8_8(5),io.dstData.result8_8(4), io.dstData.result8_8(3),io.dstData.result8_8(2),io.dstData.result8_8(1),io.dstData.result8_8(0))
        }
          .elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 32.U){
          io.wbData.result_low := Cat(Fill(32, 0.U),io.dstData.result2_32(0))
        }.elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 16.U){
          io.wbData.result_low := Cat(Fill(48, 0.U),io.dstData.result4_16(0))
        }.elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 8.U){
          io.wbData.result_low := Cat(Fill(56, 0.U),io.dstData.result8_8(0))
        }
      }
    }.otherwise{
      when(io.velem.elementNum === 1.U && io.velem.esize === 64.U) {
        io.wbData.result_low := io.dstData.result1_64(0)
      }.elsewhen(io.velem.elementNum === 2.U && io.velem.esize === 32.U) {
        io.wbData.result_low := Cat(io.dstData.result2_32(1),io.dstData.result2_32(0))
      }.elsewhen(io.velem.elementNum === 4.U && io.velem.esize === 16.U) {
        io.wbData.result_low := Cat(io.dstData.result4_16(3),io.dstData.result4_16(2),io.dstData.result4_16(1),io.dstData.result4_16(0))
      }.elsewhen(io.velem.elementNum === 8.U && io.velem.esize === 8.U) {
        io.wbData.result_low := Cat(io.dstData.result8_8(7),io.dstData.result8_8(6),io.dstData.result8_8(5),io.dstData.result8_8(4), io.dstData.result8_8(3),io.dstData.result8_8(2),io.dstData.result8_8(1),io.dstData.result8_8(0))
      }
        .elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 32.U){
        io.wbData.result_low := Cat(Fill(32, 0.U),io.dstData.result2_32(0))
      }.elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 16.U){
        io.wbData.result_low := Cat(Fill(48, 0.U),io.dstData.result4_16(0))
      }.elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 8.U){
        io.wbData.result_low := Cat(Fill(56, 0.U),io.dstData.result8_8(0))
      }
    }
  }

  //wb_hig_data
  io.wbData.result_hig := 0.U

  when(CEValid === 1.U & (secValid === 2.U)){    //low data
    when(io.vcon.long === 1.U){
      when(io.velem.elementNum === 1.U && io.velem.esize === 64.U){
        io.wbData.result_hig := io.dstData.LongResult1_128(0)(127,64)
      }.elsewhen(io.velem.elementNum === 2.U && io.velem.esize === 32.U){
        io.wbData.result_hig := io.dstData.LongResult2_64(1)
      }.elsewhen(io.velem.elementNum === 4.U && io.velem.esize === 16.U){
        io.wbData.result_hig := Cat(io.dstData.LongResult4_32(3), io.dstData.LongResult4_32(2))
      }.elsewhen(io.velem.elementNum === 8.U && io.velem.esize === 8.U){
        io.wbData.result_hig := Cat(io.dstData.LongResult8_16(7), io.dstData.LongResult8_16(6), io.dstData.LongResult8_16(5), io.dstData.LongResult8_16(4))
      }
    }.otherwise{                                           // narrow === 1/0.U || com_inst
      when(io.vdec.Q === 1.U) {                            //wb hig
        when(io.velem.elementNum === 1.U && io.velem.esize === 64.U) {
          io.wbData.result_hig := io.dstData.result1_64(0)
        }.elsewhen(io.velem.elementNum === 2.U && io.velem.esize === 32.U) {
          io.wbData.result_hig := Cat(io.dstData.result2_32(1),io.dstData.result2_32(0))
        }.elsewhen(io.velem.elementNum === 4.U && io.velem.esize === 16.U) {
          io.wbData.result_hig := Cat(io.dstData.result4_16(3),io.dstData.result4_16(2),io.dstData.result4_16(1),io.dstData.result4_16(0))
        }.elsewhen(io.velem.elementNum === 8.U && io.velem.esize === 8.U) {
          io.wbData.result_hig := Cat(io.dstData.result8_8(7),io.dstData.result8_8(6),io.dstData.result8_8(5),io.dstData.result8_8(4), io.dstData.result8_8(3),io.dstData.result8_8(2),io.dstData.result8_8(1),io.dstData.result8_8(0))
        }
          .elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 32.U){
          io.wbData.result_hig := Cat(Fill(32, 0.U),io.dstData.result2_32(0))
        }.elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 16.U){
          io.wbData.result_hig := Cat(Fill(48, 0.U),io.dstData.result4_16(0))
        }.elsewhen(io.velem.elementNum === 1.U && io.velem.esize === 8.U){
          io.wbData.result_hig := Cat(Fill(56, 0.U),io.dstData.result8_8(0))
        }
      }
    }
  }


















}